//Liste Réservation
package Model;

import java.util.Date;
import java.util.LinkedList;
import javax.swing.JOptionPane;

public class Agenda extends LinkedList<Reservation> {
    private LinkedList<Reservation> listeReservation = new LinkedList<>();
    private LinkedList<Sejour> listeSejour = new LinkedList<>();
    private static Agenda instance = null;
    
    protected Agenda(){
        //Exists only to defeat instantiation
    }
    
    public static Agenda getInstance(){
        if(instance == null){
            instance = new Agenda();
        }
        return instance;
    }
    
    public void addReservation(Reservation reservation){
        listeReservation.add(reservation);
    }
    
    public void deleteReservation(Reservation reservation){
        listeReservation.remove(reservation);
    }
    
    public void overwriteReservation(Reservation reservation){
        for(int i=0; i< listeReservation.size(); i++){
            if(listeReservation.get(i).getNumConfirmation() == reservation.getNumConfirmation()){
                listeReservation.set(i, reservation);
                break;
            }
        }
    }
    
    public int getNextID(){
        int nextID = 1;
        if(listeReservation.size() != 0)
            nextID = listeReservation.get(listeReservation.size() - 1).getNumConfirmation() + 1;
        return nextID;
    }
    
    public LinkedList<LigneReservation> trouverReservationACeMoment(LigneReservation ligneReservation){
        LinkedList<LigneReservation> ReservationAtThatMoment = new LinkedList<>();
        //check all the reservation saved
        for(int i = 0; i < listeReservation.size(); i++){
            Reservation currentReservation = listeReservation.get(i);
            
            for(int j = 0; j < currentReservation.getligneReservation().size(); j++){
                LigneReservation currentLigneReservation = currentReservation.getligneReservation().get(j);
                if((isBetween(currentLigneReservation.getDteArrive(), ligneReservation.getDteArrive(), ligneReservation.getDteFin()) ||
                        isBetween(currentLigneReservation.getDteFin(), ligneReservation.getDteArrive(), ligneReservation.getDteFin()))&& 
                        currentLigneReservation.getCat().getNomCategorie().equals(ligneReservation.getCat().getNomCategorie())){
                    ReservationAtThatMoment.add(currentLigneReservation);
                }
            }
        } 
        
        return ReservationAtThatMoment;
    }
    
    public LinkedList<LigneReservation> trouverReservationACeMoment(Date dteDebut, Date dteFin){
        LinkedList<LigneReservation> ReservationAtThatMoment = new LinkedList<>();
        //check all the reservation saved
        for(int i = 0; i < listeReservation.size(); i++){
            Reservation currentReservation = listeReservation.get(i);
            
            for(int j = 0; j < currentReservation.getligneReservation().size(); j++){
                LigneReservation currentLigneReservation = currentReservation.getligneReservation().get(j);
                
                if((isBetween(currentLigneReservation.getDteArrive(), dteDebut, dteFin) ||
                        isBetween(currentLigneReservation.getDteFin(), dteDebut, dteFin))){
                    ReservationAtThatMoment.add(currentLigneReservation);
                }
            }
        } 
        
        return ReservationAtThatMoment;
    }
    
    public Reservation TrouverReservation(int numConf){
        for(int i=0;i< this.listeReservation.size();i++){
            if (this.listeReservation.get(i).getNumConfirmation() == numConf)
                return this.listeReservation.get(i);
        }
        return null;
    }
    
    public Reservation TrouverReservation(String nomClient, String numTel){
        for(int i=0;i< this.listeReservation.size();i++){
            if (this.listeReservation.get(i).getClient().getNomClient().equals(nomClient) && this.listeReservation.get(i).getClient().getNumTel().equals(numTel))
                return this.listeReservation.get(i);
        }
        return null;
    }
    
    /**
     * check if there is a place for the specified ligneReservation
     * @param ligneReservation the ligneReservation you want to add to the reservation in creation
     * @return true if there is a place in the hotel at that moment for the specified number of the specified category
     */
    public boolean verifierDisponibilite(LigneReservation ligneReservation){
        LinkedList<LigneReservation> ReservationAtThatMoment = trouverReservationACeMoment(ligneReservation);
        
        boolean enoughPlace = isThereEnoughPlace(ligneReservation, ReservationAtThatMoment);
        return enoughPlace;
    }
    
    public boolean isBetween(Date dteChecking, Date dteDebut, Date dteFin){
        if((dteChecking.equals(dteDebut) || dteChecking.after(dteDebut)) && (dteChecking.equals(dteFin) || dteChecking.before(dteFin))){
            return true;
        }
        return false;
    }

    private boolean isThereEnoughPlace(LigneReservation reservation, LinkedList<LigneReservation> ReservationAtThatMoment) {
        int nbChambreTotal = TestData.getNbChambre(reservation.getCat());
        
        int NbChambreOccupe =0;
        for(int i=0;i<ReservationAtThatMoment.size();i++){
            NbChambreOccupe += ReservationAtThatMoment.get(i).getNombreChambre();
        }
        
        if((nbChambreTotal - NbChambreOccupe) >= reservation.getNombreChambre()){
            return true;
        }
        return false;
    }

    public String[][] AfficherCategorie(Date dteDebut, Date dteFin){
        //Trouver les réservation a ce moment
        LinkedList<LigneReservation> ReservationAtThatMoment = trouverReservationACeMoment(dteDebut, dteFin);
        
        //Avoir la liste des chambres disponible et la liste des catégorie
        LinkedList<Chambre> listeChambreDispo = getListeCatDispo(ReservationAtThatMoment);
        LinkedList<Categorie> listeCategorie = TestData.getListeCategorie();
        
        //créer le string array
        String[][] data = new String[listeChambreDispo.size()][2];
        for(int i=0;i<listeCategorie.size();i++){
            data[i][0] = String.valueOf(listeCategorie.get(i).getNomCategorie());
            data[i][1] = Integer.toString(getNbChambreLibreByCategorie(listeChambreDispo,listeCategorie.get(i)));
        }
        
        return data;
    }
    
    private LinkedList<Chambre> getListeCatDispo(LinkedList<LigneReservation> ReservationAtThatMoment){
        LinkedList<Chambre> listeChambreDispo = TestData.getListeChambre();
        
        //Parcour les lr
        for(int i=0; i< ReservationAtThatMoment.size();i++){
            LigneReservation lr = ReservationAtThatMoment.get(i);
            
            //Enlever la chambre qui a la meme catégorie que la lr
            for(int j = 0; j< listeChambreDispo.size();j++){
                Chambre c = listeChambreDispo.get(j);
                if (c.getCategorie().getNomCategorie().equals(lr.getCat().getNomCategorie())){
                    for(int k=0; k < lr.getNombreChambre(); k++){
                        listeChambreDispo.remove(j);
                    }
                    break;
                }
            }
        }
        
        return listeChambreDispo;
    }
    
    private int getNbChambreLibreByCategorie(LinkedList<Chambre> listeChambre, Categorie cat){
        int NbCat = 0;
        for(int i=0; i< listeChambre.size();i++){
            if(listeChambre.get(i).getCategorie().getNomCategorie().equals(cat.getNomCategorie())){
                NbCat++;
            }
        }
        return NbCat;
    }
    
    
    //******************GESTION DU SÉJOUR**********************//
    public int getNextIdSejour(){ 
        return (this.listeSejour.size()+1);
    }
    
    public String[][] AfficherChambreLibreParCategorie(Date dteDebut, Date dteFin, Categorie cat){
        //Trouver les réservation a ce moment
        LinkedList<Sejour> SejourAtThatMoment = trouverSejourAceMomentDate(dteDebut, dteFin);
        
        //Avoir la liste des chambres disponible
        LinkedList<Chambre> listeChambreDispo = getListeChambreDispo(SejourAtThatMoment);
        listeChambreDispo = FiltrerParCategorie(listeChambreDispo, cat);
        
        //créer le string array
        String[][] data = new String[listeChambreDispo.size()][2];
        for(int i=0;i<listeChambreDispo.size();i++){
            data[i][0] = Integer.toString(listeChambreDispo.get(i).getNumeroChambre());
            data[i][1] = listeChambreDispo.get(i).getCategorie().getNomCategorie();
        }
        
        return data;
    }
    
    public String[][] AfficherChambreLibreParCategorie(Date dteDebut, Date dteFin){
        //Trouver les réservation a ce moment
        LinkedList<Sejour> SejourAtThatMoment = trouverSejourAceMomentDate(dteDebut, dteFin);
        
        //Avoir la liste des chambres disponible
        LinkedList<Chambre> listeChambreDispo = getListeChambreDispo(SejourAtThatMoment);
        
        //créer le string array
        String[][] data = new String[listeChambreDispo.size()][2];
        for(int i=0;i<listeChambreDispo.size();i++){
            data[i][0] = Integer.toString(listeChambreDispo.get(i).getNumeroChambre());
            data[i][1] = listeChambreDispo.get(i).getCategorie().getNomCategorie();
        }
        return data;
    }
    
    public String[][] AfficherChambreLibreParCategorie(int idSejour){
            
        Sejour sejour = TrouverSejour(idSejour);
        
        return AfficherCategorie(sejour.getDateDebut(), sejour.getDateFin());
    }
        
    public LinkedList<Chambre> FiltrerParCategorie(LinkedList<Chambre> listeChambre, Categorie cat){
        for(int i=0; i< listeChambre.size();i++){
            if(!listeChambre.get(i).getCategorie().getNomCategorie().equals(cat.getNomCategorie())){
                listeChambre.remove(i);
                i--;
            }
        }
        
        return listeChambre;
    }
    
    public LignePaiement TerminerChambre(int numChambre){
        LignePaiement paiement = null;
        Chambre chambre = TestData.getChambre(numChambre);
        
        if(chambre == null){
            JOptionPane.showMessageDialog(null, "La chambre spécifié n'existe pas, Veuillez choisir un autre numéro de chambre",
                    "Mauvais numéro de chambre", 0);
        }else{
            boolean chambreOccupe = false;
            Sejour sejourChambre = new Sejour();
            
            try{
                for(int i = 0; i < listeSejour.size(); i++){
                    LinkedList<Chambre> listeChambre = listeSejour.get(i).getListeChambre();

                    for(int j = 0; j< listeChambre.size(); j++){
                        if(listeChambre.get(j).getNumeroChambre() == numChambre){
                            chambreOccupe = true;
                            sejourChambre = listeSejour.get(i);
                        }
                    }
                }
            }catch(Exception e){
                
            }
            if(!chambreOccupe || sejourChambre.getDateDebut().after(new Date())){
                 JOptionPane.showMessageDialog(null, "La chambre spécifié n'est pas celle dans laquelle le client a sejourné",
                        "Mauvais numéro de chambre", 0);
                 chambre = null;
            }else{
                boolean terminerChambre = false;
                Date closedDate = new Date();
                if(sejourChambre.getDateFin().after(new Date())){
                    int TerminerSejour = JOptionPane.showConfirmDialog(null, "Le séjour de la chambre n'est pas fini.\n"
                            + "Êtes-vous sur de vouloir terminer le sejour presentement?", "La chambre est en cours d'utilisation", JOptionPane.OK_CANCEL_OPTION);
                    if(TerminerSejour == JOptionPane.OK_OPTION){
                        terminerChambre = true;
                    }
                }else{
                    terminerChambre = true;
                    closedDate = sejourChambre.getDateFin();
                }
                if(terminerChambre){
                    for(int i = 0; i < listeSejour.size(); i++){
                        if(sejourChambre.equals(listeSejour.get(i))){
                            if(listeSejour.get(i).getListeChambre().size() == 1){
                                listeSejour.remove(sejourChambre);
                            }else{
                                for(int j = 00; j < listeSejour.get(i).getListeChambre().size(); j++){
                                    if(listeSejour.get(i).getListeChambre().get(j).getNumeroChambre() == numChambre){
                                        listeSejour.get(i).getListeChambre().remove(j);
                                    }
                                }
                            }
                        }
                    }

                    paiement = new LignePaiement(sejourChambre.getDateDebut(), 
                            closedDate, chambre);
                }
                
            }
        }
        return paiement;
    }

    public LinkedList<Sejour> trouverSejourAceMomentDate(Date dteDebut, Date dteFin){
        LinkedList<Sejour> sejourACeMoment = new LinkedList<>();
        //check all the reservation saved
        for(int i = 0; i < listeSejour.size(); i++){
            Sejour currentSejour = listeSejour.get(i);
                
            if((isBetween(currentSejour.getDateDebut(), dteDebut, dteFin) || isBetween(currentSejour.getDateFin(), dteDebut, dteFin))){
                sejourACeMoment.add(currentSejour);
            }
        } 
        return sejourACeMoment;
    }
    
    public Sejour TrouverSejour(int idSejour){
        //check all the reservation saved
        Sejour currentSejour = new Sejour();
        for(int i = 0; i < listeSejour.size(); i++){
            currentSejour = listeSejour.get(i);
                
            if(currentSejour.getNum() == idSejour){
                return currentSejour;
            }
        } 
        
        return null;
    }
    
    private LinkedList<Chambre> getListeChambreDispo(LinkedList<Sejour> SejourAceMoment){
        LinkedList<Chambre> listeChambreDispo = TestData.getListeChambre();
        
        //Parcours les séjours
        for(int i=0; i< SejourAceMoment.size();i++){
            Sejour sjr = SejourAceMoment.get(i);
            
            
            //Parcour la liste de chambre du séjour
            for (int j=0;j<SejourAceMoment.get(i).getListeChambre().size();j++){
                //Enlever la chambre du séjour
                for(int k = 0; k < listeChambreDispo.size();k ++){
                    if (listeChambreDispo.get(k).getNumeroChambre() == SejourAceMoment.get(i).getListeChambre().get(j).getNumeroChambre()){
                        listeChambreDispo.remove(k);
                        break;
                    }
                }
            }
        }
        return listeChambreDispo;
    }
    
    public void updateSejour(Sejour sejour) {
        this.listeSejour.add(sejour);
    }
    
    public String[][] lireChambreSejour(int idSejour){
        String[][] array = new String[0][0];
        for(int i=0;i< this.listeSejour.size();i++){
            if (this.listeSejour.get(i).getNum() == idSejour){
                array = new String[this.listeSejour.get(i).getListeChambre().size()][2];
                for(int j=0;j<this.listeSejour.get(i).getListeChambre().size();j++){
                    array[j][0] = Integer.toString(this.listeSejour.get(i).getListeChambre().get(j).getNumeroChambre());
                    array[j][1] = this.listeSejour.get(i).getListeChambre().get(j).getCategorie().getNomCategorie();
                }
            }
        }
        return array;
    }
    
    public boolean verifierDisponibilite(Sejour sejour){
        LinkedList<Sejour> SejourAceMoment = trouverSejourAceMomentDate(sejour.getDateDebut(), sejour.getDateFin());
        
        LinkedList<Chambre> listeChambre = getListeChambreDispo(SejourAceMoment);
        
        if(listeChambre.size() < sejour.getListeChambre().size())
            return false;
        return true;
    }
    
    public Chambre getChambreDispo(Date dteDebut, Date dteFin, Categorie categorie){
        //Trouver les réservation a ce moment
        LinkedList<Sejour> SejourAtThatMoment = trouverSejourAceMomentDate(dteDebut, dteFin);
        
        //Avoir la liste des chambres disponible
        LinkedList<Chambre> listeChambreDispo = getListeChambreDispo(SejourAtThatMoment);
        listeChambreDispo = FiltrerParCategorie(listeChambreDispo, categorie);
        
        return listeChambreDispo.getFirst();
    }
    

}